/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package xowl.interpreter;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 *
 * @author Laurent WOUTERS
 */
public class Application {
    private static final String libsPath = "libs/";
    private static final String paramFile = "--file";
    private static final String paramEmit = "--emit";

    public static void main(String[] args) {
        xowl.utils.logging.Logger log = new xowl.utils.logging.Logger(Application.class.getName(), org.apache.log4j.Level.INFO);
        if (args.length == 0) {
            log.fatal(Application.class.getName(), "No parameters");
            return;
        }
        if (paramFile.equals(args[0])) {
            Interpreter.config(log, libsPath);
            log.info(Application.class.getName(), "Config file: " + args[1]);
            xowl.utils.config.Configuration config = new xowl.utils.config.Configuration();
            try { config.load(args[1]); }
            catch (java.io.IOException ex) {
                log.fatal(Application.class.getName(), "Failed to load configuration file: " + args[1], ex);
                return;
            }
            xowl.interpreter.Application app = new xowl.interpreter.Application(config, log);
            app.run();
        } else if (paramEmit.equals(args[0])) {
            String input = args[1];
            String output = args[2];
            String className = args[3];
            xowl.utils.config.ClassGenerator gen = new xowl.utils.config.ClassGenerator(input, output, className);
            try { gen.generate(); }
            catch (java.io.IOException ex) {
                log.fatal(Application.class.getName(), "Failed emit code", ex);
                return;
            }
        }
    }
    

    private static class InputSource {
        public String source;
        public OWL2Syntax type;
    }

    private xowl.utils.logging.Logger log;
    private String inputBackend;
    private List<InputSource> inputSources;
    private String inputMain;
    private List<Object> inputParams;
    private xowl.lang.runtime.Value outputValue;

    public Application(xowl.utils.config.Configuration config, xowl.utils.logging.Logger log) {
        this.log = log;
        this.inputBackend = "JenaPellet";
        this.inputSources = new ArrayList<InputSource>();
        this.inputParams = new ArrayList<Object>();
        loadConfig(config);
    }
    
    private void loadConfig(xowl.utils.config.Configuration config) {
        String value = config.getValue("backend");
        if (value != null) {
            inputBackend = value;
        }

        List<String> values = config.getValues(null, "input");
        for (String val : values) {
            String[] parts = val.split("\\|");
            InputSource input = new InputSource();
            input.source = parts[0].trim();
            input.type = OWL2Syntax.valueOf(parts[1].trim());
            inputSources.add(input);
        }

        value = config.getValue("main");
        if (value != null)
            inputMain = value;

        value = config.getValue("param");
        if (value != null)
            inputParams.add(loadConfig_ParseValue(value));
    }
    private Object loadConfig_ParseValue(String value) {
        if (value.startsWith("\""))
            return value.substring(1, value.length() - 1);
        Scanner scanner = new Scanner(value);
        if (scanner.hasNextBoolean()) return scanner.nextBoolean();
        if (scanner.hasNextInt()) return scanner.nextInt();
        if (scanner.hasNextFloat()) return scanner.nextFloat();
        return scanner.next();
    }

    public void run() {
        Thread thread = Interpreter.createThread(createRepository(inputBackend));
        for (InputSource source : inputSources)
            thread.getRepository().loadOntology(source.source, source.type);
        java.lang.System.out.println();
        java.lang.System.out.println("== XOWL Interpretation Begin ==");
        try {
            xowl.lang.runtime.Value function = thread.getRepository().resolveEntity(inputMain);
            xowl.lang.runtime.Value[] params = new xowl.lang.runtime.Value[inputParams.size()];
            for (int i=0; i!=inputParams.size(); i++)
                params[i] = thread.getRepository().getLiteral(inputParams.get(i));
            outputValue = thread.run(function, params);
            if (outputValue != null)
                java.lang.System.out.println(xowl.utils.Values.toString(outputValue));
        } catch (XOWLException ex) { log.fatal(Application.class.getName(), ex.getHeadline(), ex); }
        java.lang.System.out.println("== XOWL Interpretation End ==");
    }
    
    private Repository createRepository(String backend) {
        if (backend.equals("Native")) return Interpreter.createRepositoryNative(log);
        if (backend.equals("NativeRDF")) return Interpreter.createRepositoryNativeRDF(log);
        if (backend.equals("JenaPellet")) return Interpreter.createRepositoryJenaPellet(log);
        return null;
    }
}
